home *** CD-ROM | disk | FTP | other *** search
- #include <ctype.h>
- #include <fcntl.h>
- #include <linux/hdreg.h>
- #include <linux/fs.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/sysmacros.h>
- #include <sys/wait.h>
- #include <unistd.h>
-
- #include "hd.h"
- #include "install.h"
- #include "log.h"
- #include "newt.h"
- #include "run.h"
- #include "scsi.h"
- #include "windows.h"
-
- extern int testing;
-
- struct fdiskTag {
- int tag;
- int type;
- } ;
-
- #if defined(__sparc__)
- const struct fdiskTag fdiskTags[] = {
- { 0x05, PART_IGNORE },
- { 0x82, PART_SWAP },
- { 0x83, PART_EXT2 },
- { 0, 0 },
- };
- #else
- const struct fdiskTag fdiskTags[] = {
- { 0x01, PART_DOS },
- { 0x04, PART_DOS },
- { 0x05, PART_IGNORE },
- { 0x06, PART_DOS },
- { 0x07, PART_HPFS },
- { 0x82, PART_SWAP },
- { 0x83, PART_EXT2 },
- { 0, 0 },
- };
- #endif
-
- struct hd {
- char * device;
- int major, minor;
- };
-
- struct hd static possibleDrives[] = {
- #ifndef __sparc__
- { "hda", 3, 0 },
- { "hdb", 3, 64 },
- { "hdc", 22, 0 },
- { "hdd", 22, 64 },
- { "hde", 33, 0 },
- { "hdf", 33, 64 },
- { "hdg", 34, 0 },
- { "hdh", 34, 64 },
- #endif
- { "sda", 8, 0 },
- { "sdb", 8, 16 },
- { "sdc", 8, 32 },
- { "sdd", 8, 48 },
- { "sde", 8, 64 },
- { "sdf", 8, 80 },
- { "sdg", 8, 96 },
- { "sdh", 8, 112 },
-
- };
-
- static void parseLabelLine(char * device, char * start, int * numPartitions,
- struct partition partitions[15]) {
- char * str = start;
- char * chptr;
- char devbuf[2];
-
- if (*str++ != ' ') return;
- if (*str++ != ' ') return;
-
- if (*str < 'a' || *str > 'h') return;
- if (*(str + 1) != ':') return;
-
- strcpy(partitions[*numPartitions].device, device);
- devbuf[0] = *str - 'a' + '1';
- devbuf[1] = '\0';
- strcat(partitions[*numPartitions].device, devbuf);
- str += 2;
-
- while (*str && isspace(*str)) str++;
- if (!*str) return;
-
- partitions[*numPartitions].size = strtol(str, &chptr, 10);
- partitions[*numPartitions].size /= 2; /* we want 1k blocks */
- if (!chptr || !isspace(*chptr)) return;
- str = chptr;
-
- while (isspace(*str)) str++;
- if (!*str) return;
-
- partitions[*numPartitions].begin = strtol(str, &chptr, 10);
- if (!chptr || !isspace(*chptr)) return;
- str = chptr;
-
- partitions[*numPartitions].end = partitions[*numPartitions].size * 2 +
- partitions[*numPartitions].begin;
-
- while (isspace(*str)) str++;
- if (!*str) return;
-
- if (!strncmp(str, "ext2", 4)) {
- partitions[*numPartitions].type = PART_EXT2;
- strcpy(partitions[*numPartitions].tagName, "Linux native");
- } else if (!strncmp(str, "swap", 4)) {
- partitions[*numPartitions].type = PART_SWAP;
- strcpy(partitions[*numPartitions].tagName, "Linux swap");
- } else {
- partitions[*numPartitions].type = PART_OTHER;
- strcpy(partitions[*numPartitions].tagName, "Other");
- }
-
- partitions[*numPartitions].bootLabel = NULL;
-
- logMessage("found partition %s", partitions[*numPartitions].device);
-
- (*numPartitions)++;
- }
-
- static void parseFdiskLine(char * device, char * start, int * numPartitions,
- struct partition partitions[15]) {
- int tag, i;
- char * str = start;
- char * chptr;
-
- if (*str != '/') return;
-
- if (strlen(str) < 60) return;
-
- /* grab the partition number */
- str += 8;
- chptr = str;
-
- if (!isdigit(*chptr)) return;
- while (*chptr && isdigit(*chptr)) chptr++;
- if (!*chptr) return;
-
- *chptr = '\0';
- strcpy(partitions[*numPartitions].device, device);
- strcat(partitions[*numPartitions].device, str);
- str = chptr + 1;
-
- /* go to the "Begin" field, skipping the '*' which marks a bootable
- partition and the 'u|r' fields which can occur on a Sun disklabel */
- while (*str && (isspace(*str) || *str == '*' || *str == 'u' ||
- *str == 'r')) str++;
- if (!*str) return;
-
- /* skip the Begin: field (but make sure it's a number */
- if (!isdigit(*str)) return;
- while (isdigit(*str)) str++;
- if (!*str || !isspace(*str)) return;
-
- /* go to the first digit in the "Start" field */
- while (isspace(*str)) str++;
- if (!*str) return;
-
- partitions[*numPartitions].begin = strtol(str, &chptr, 10);
- if (!chptr || !isspace(*chptr)) return;
- str = chptr;
-
- /* go to the first digit in the "End" field */
- while (isspace(*str)) str++;
- if (!*str) return;
-
- partitions[*numPartitions].end = strtol(str, &chptr, 10);
- if (!chptr || !isspace(*chptr)) return;
- str = chptr;
-
- /* go to the first digit in the "Size" field */
- while (isspace(*str)) str++;
- if (!*str) return;
-
- partitions[*numPartitions].size = strtol(str, &chptr, 10);
- if (!chptr || (*chptr != '-' && *chptr != '+' && !isspace(*chptr)))
- return;
-
- str = chptr + 1;
-
- /* go to the first digit in the "Tag" field */
- while (isspace(*str)) str++;
- if (!*str) return;
- tag = strtol(str, &chptr, 16);
-
- partitions[*numPartitions].type = PART_OTHER;
- for (i = 0; fdiskTags[i].tag; i++) {
- if (fdiskTags[i].tag == tag) {
- partitions[*numPartitions].type = fdiskTags[i].type;
- break;
- }
- }
-
- str = chptr;
- while (isspace(*str)) str++;
- if (!*str) return;
-
- strcpy(partitions[*numPartitions].tagName, str);
- partitions[*numPartitions].bootLabel = NULL;
-
- logMessage("found partition %s", partitions[*numPartitions].device);
-
- (*numPartitions)++;
- }
-
- static int findPartitions(struct hd hd, int * numPartitions,
- struct partition partitions[15]) {
- char devBuf[20];
- int fd;
- char * fdiskOutput;
- char * fdiskArgs[] = { NULL, NULL, NULL };
- char * start, * end;
- int oldTesting;
- int len;
- char * cmd;
- struct hd_geometry geo;
- int labelMode = 0;
- #if defined(__alpha__)
- unsigned short magic;
- unsigned int fdiskMagic = 0xAA55;
- #endif
-
- if (testing)
- cmd = "/sbin/fdisk";
- else
- cmd = "/usr/bin/fdisk";
-
- fdiskArgs[0] = cmd;
-
- *numPartitions = 0;
-
- /* don't bother with any of this if the main device doesn't exist
- or doesn't look like a hard drive */
- sprintf(devBuf, "/tmp/%s", hd.device);
- mknod(devBuf, S_IFBLK | 0600, makedev(hd.major, hd.minor));
- fd = open(devBuf, O_RDONLY);
- if (fd < 0) {
- unlink(devBuf);
- return 0;
- }
-
- /* make sure this isn't an IDE CD or tape drive */
- if (ioctl(fd, HDIO_GETGEO, &geo)) {
- logMessage("/dev/%s doesn't look like a hard drive", hd.device);
- unlink(devBuf);
- close(fd);
- return 0;
- }
-
- #if defined(__alpha__)
- /* is this a labeled disk? */
- /* This test used to just look for the disklabel magic, but that
- got left around on fdisks drives much of the time. This check
- seems more reliable */
- lseek(fd, 510, SEEK_SET);
- if (read(fd, &magic, sizeof(magic)) == sizeof(magic))
- labelMode = (magic != fdiskMagic);
-
- if (labelMode)
- logMessage("/dev/%s is disklabeled", hd.device);
- else
- logMessage("/dev/%s is fdisked", hd.device);
- #endif
-
- close(fd);
-
- oldTesting = testing;
- testing = 0;
- fdiskArgs[1] = devBuf;
- if (labelMode)
- runProgramIO(RUN_NOLOG, cmd, fdiskArgs, "b\np\nq\n", &fdiskOutput);
- else
- runProgramIO(RUN_NOLOG, cmd, fdiskArgs, "p\nq\n", &fdiskOutput);
- unlink(devBuf);
- testing = oldTesting;
-
- start = fdiskOutput;
- len = strlen(start);
- while (((start - fdiskOutput) < len) && (end = strchr(start, '\n'))) {
- *end = '\0';
- if (labelMode)
- parseLabelLine(hd.device, start, numPartitions, partitions);
- else
- parseFdiskLine(hd.device, start, numPartitions, partitions);
-
- start = end + 1;
- }
- free(fdiskOutput);
-
- return 0;
- }
-
- int findAllPartitions(struct partitionTable * table) {
- int numPartitions;
- int i;
- struct partition parts[16];
- struct partition * allParts = NULL;
- int numAllParts = 0;
-
- winStatus(30, 3, "Hard Drives", "Scanning hard drives...");
-
- for (i = 0; i < (sizeof(possibleDrives) / sizeof(*possibleDrives)); i++) {
- findPartitions(possibleDrives[i], &numPartitions, parts);
- if (!numPartitions) continue;
-
- if (!numAllParts) {
- numAllParts = numPartitions;
- allParts = malloc(sizeof(*allParts) * numAllParts);
- memcpy(allParts, parts, sizeof(*allParts) * numAllParts);
- } else {
- allParts = realloc(allParts, sizeof(*allParts) *
- (numAllParts + numPartitions));
- memcpy(allParts + numAllParts, parts,
- sizeof(*allParts) * numPartitions);
- numAllParts += numPartitions;
- }
- }
-
- table->count = numAllParts;
- table->parts = allParts;
-
- newtPopWindow();
-
- return 0;
- }
-
- int partitionDrives(void) {
- int drivesPresent[sizeof(possibleDrives) / sizeof(*possibleDrives)];
- int numDrivesPresent = 0;
- int childpid;
- int i, fd, rc;
- int haveEdited = 0;
- char devBuf[100], idBuf[3];
- newtComponent cancel, done, edit, text, listbox, f, answer, okay, form;
- struct hd_geometry geo;
- struct hd * currhd;
- char * cmd;
- int status;
- struct scsiDeviceInfo * sdi, * thissd;
- int reboot = 0;
- struct hd_driveid ideids[sizeof(possibleDrives) / sizeof(*possibleDrives)];
-
- if (testing)
- cmd = "/sbin/fdisk";
- else
- cmd = "/usr/bin/fdisk";
-
- for (i = 0; i < sizeof(possibleDrives) / sizeof(*possibleDrives); i++) {
- sprintf(devBuf, "/tmp/%s", possibleDrives[i].device);
- mknod(devBuf, S_IFBLK | 0600,
- makedev(possibleDrives[i].major, possibleDrives[i].minor));
- fd = open(devBuf, O_RDONLY);
- unlink(devBuf);
- if (fd < 0) {
- continue;
- }
-
- logMessage("successfully opened: %s", devBuf);
-
- if (possibleDrives[i].device[0] == 'h') {
- /* make sure this isn't an IDE CD or tape drive */
- if (ioctl(fd, HDIO_GETGEO, &geo)) {
- logMessage("\tHDIO_GETGEO ioctl failed - probably cd or tape");
- close(fd);
- continue;
- } else {
- if (ioctl(fd, HDIO_GET_IDENTITY, &ideids[numDrivesPresent])) {
- ideids[numDrivesPresent].model[0] = '\0';
- }
- }
- }
-
- close(fd);
-
- drivesPresent[numDrivesPresent++] = i;
- }
-
- if (!numDrivesPresent) {
- newtOpenWindow(18, 6, 44, 11, "Setup Swap");
- text = newtTextbox(1, 1, 42, 4, NEWT_TEXTBOX_WRAP);
- newtTextboxSetText(text, "You don't have any hard drives available! "
- "You probably forgot to configure a SCSI "
- "controller.");
-
- okay = newtButton(17, 7, "Ok");
-
- form = newtForm(NULL, NULL, 0);
- newtFormAddComponents(form, text, okay, NULL);
-
- newtRunForm(form);
- newtFormDestroy(form);
- newtPopWindow();
-
- return INST_ERROR;
- }
-
- if (scsiDeviceAvailable()) {
- if ((rc = scsiGetDevices(&sdi))) return rc;
- } else {
- sdi = NULL;
- }
-
- newtOpenWindow(10, 3, 60, 17, "Partition Disks");
- text = newtTextbox(1, 1, 56, 5, NEWT_TEXTBOX_WRAP);
- #ifdef __i386__
- newtTextboxSetText(text,
- "To install Red Hat Linux, you must have at least "
- "one parition of 50 MB dedicated to Linux. We suggest "
- "placing that partition on one of the first two hard "
- "drives in your system so you can boot into Linux "
- "with LILO.");
- #else
- newtTextboxSetText(text,
- "To install Red Hat Linux, you must have at least "
- "one parition of 50 MB dedicated to Linux.");
- #endif
-
- listbox = newtListbox(10, 7, numDrivesPresent < 5 ? numDrivesPresent : 5,
- (numDrivesPresent <= 5 ? NEWT_FLAG_NOSCROLL : 0) |
- NEWT_LISTBOX_RETURNEXIT);
-
- for (i = 0; i < numDrivesPresent; i++) {
- sprintf(devBuf, "/dev/%s", possibleDrives[drivesPresent[i]].device);
-
- if (sdi && !strncmp(possibleDrives[drivesPresent[i]].device, "sd", 2))
- {
- thissd = sdi;
- while (thissd->info &&
- strcmp(thissd->deviceName,
- possibleDrives[drivesPresent[i]].device)) thissd++;
- if (thissd->info) {
- sprintf(idBuf, "%d", thissd->id);
- strcat(devBuf, " - SCSI ID ");
- strcat(devBuf, idBuf);
- strcat(devBuf, " ");
- strcat(devBuf, thissd->info);
- }
- } else if (ideids[i].model[0]) {
- strcat(devBuf, " - Model ");
- strcat(devBuf, ideids[i].model);
- }
-
- newtListboxAddEntry(listbox, devBuf, possibleDrives + drivesPresent[i]);
- }
-
- done = newtButton(7, 13, "Done");
- edit = newtButton(24, 13, "Edit");
- cancel = newtButton(41, 13, "Cancel");
-
- f = newtForm(NULL, NULL, 0);
- newtFormAddComponents(f, text, listbox, done, edit, cancel, NULL);
- newtFormSetCurrent(f, done);
-
- do {
- answer = newtRunForm(f);
-
- if (answer == edit || answer == listbox) {
- haveEdited = 1;
- currhd = newtListboxGetCurrent(listbox);
-
- sprintf(devBuf, "/tmp/%s", currhd->device);
- mknod(devBuf, S_IFBLK | 0600,
- makedev(currhd->major, currhd->minor));
-
- newtPopWindow();
- newtSuspend();
- for (i = 0; i < 25; i++) puts("");
- printf("This is the fdisk program for partitioning your drive. It "
- "is running\non /dev/%s.\n\n", currhd->device);
-
- logMessage("running fdisk on %s", devBuf);
-
- if (!(childpid = fork())) {
- execl(cmd, cmd, devBuf, NULL);
- return -1;
- }
-
- waitpid(childpid, &status, 0);
-
- newtResume();
- newtOpenWindow(10, 3, 60, 17, "Partition Disks");
- }
- } while (answer != done && answer != cancel && answer != f);
-
- newtFormDestroy(f);
- newtPopWindow();
-
- if (haveEdited) {
- for (i = 0; i < numDrivesPresent; i++) {
- sprintf(devBuf, "/tmp/%s", possibleDrives[drivesPresent[i]].device);
- mknod(devBuf, S_IFBLK | 0600,
- makedev(possibleDrives[drivesPresent[i]].major,
- possibleDrives[drivesPresent[i]].minor));
- fd = open(devBuf, O_RDONLY);
- unlink(devBuf);
- if (fd < 0) reboot = 1;
-
- if (ioctl(fd, BLKRRPART, 0)) reboot = 1;
- close(fd);
- }
- }
-
- if (reboot) {
- winMessage(14, 6, 52, 12, "Reboot Needed",
- "The kernel is unable to read your new partitioning "
- "information, probably because you modified extended "
- "partitions. While this is not critical, you must "
- "reboot your machine before proceeding. Insert the "
- "Red Hat boot disk now and press Return to reboot "
- "your system.");
- newtFinished();
- exit(0);
- }
-
- if (answer == cancel)
- return INST_CANCEL;
-
- return 0;
- }
-